<!DOCTYPE html>
<html lang="en-GB">
<head>
    <meta charset="utf-8" />
    <title>slabText &mdash; a jQuery plugin for creating big, bold &amp; responsive headlines</title>
    <!-- slabtext stylesheet -->
    <link href="css/slabtext.css" rel="stylesheet" type="text/css" />
    <!-- demo styles inline -->
    <style>
        html,
        body
            {
            background:#fcfcfc;
            color:#444;
            }
        body
            {
            font: 16px/1.8 "Open Sans", "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
            width:92%;
            padding:20px 0;
            margin:0 auto;
            }
       .content-wrap,
       footer
            {
            margin:0 auto;
            max-width:50em;
            }
        /* http://css-tricks.com/simple-styles-for-horizontal-rules/ */
        hr
            {
            border:0;
            height:1px;
            background-image: -webkit-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0));
            background-image:    -moz-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0));
            background-image:     -ms-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0));
            background-image:      -o-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0));
            background-image:         linear-gradient(to left, rgba(0,0,0,0) 0%, rgba(0,0,0,0.75) 50%, rgba(0,0,0,0) 100%);
            }
        .col-1,
        .col-2
            {
            float:none;
            margin:0;
            width:100%;
            }
        .col-1 p,
        .col-2 p
            {
            color:#888;
            font-size:80%;
            text-align:center;
            }
        a
            {
            color:#111;
            }
        h1 a
            {
            text-decoration:none;
            }
        h1 a:hover
            {
            color:#a82222;
            }
        h1, h2
            {
            font-weight:700;
            }
        p
            {
            margin:0 0 1.6em 0;
            line-height:1.6;
            }
        footer
            {
            border-top:3px double #aaa;
            border-bottom:3px double #aaa;
            padding-top:1em;
            padding-bottom:0.4em;
            margin-bottom:1em;
            }
        sup a
            {
            text-decoration:none;
            }
        pre
            {
            /*line-height:1.2;*/
            padding:1em;
            background: #33343f;

            }
        code,
        dt
            {
            font-family: Consolas, Monaco, "Andale Mono", "DejaVu Sans Mono", monospace;
            color:#222;
            }
        pre code
            {
            display:block;
            padding:1em;
            font-size: 95%;
            line-height: 140%;
            white-space: pre;
            white-space: pre-wrap;
            white-space: -moz-pre-wrap;
            white-space: -o-pre-wrap;
            background: #23241f;
            overflow-y: auto;
            overflow-x: hidden;
            color: #f8f8f2;
            }
        .hl-1
            {
            color: #f92672;
            }
        .hl-2
            {
            color: #e6db74;
            }
        .u--clear-float
            {
            clear:both;
            }
        .amp
            {
            font-family:Baskerville,'Goudy Old Style',Palatino,'Book Antiqua',serif;
            font-style:italic;
            font-weight:lighter;
            }
        /* Set font-sizes for the headings to be given the slabText treatment */
        h1
            {
            text-align:left;
            font-family:"Oswald", "Arial Black", Gadget, sans-serif;
            text-transform:uppercase;
            line-height:1;
            color:#222;
            }
        /* Adjust the line-height for all headlines contining small letter
           counts as the font will probably be rendered at a large scale
           and we want to reduce the interline whitespace slightly.
           This isn't an exact art and the line-height you set will also depend
           on the font used.
           Headlines that have been preset do not have this utility class added
           to the existing spans (but individual lines can always be targetted
           using the nth-child selector as shown below) */
        .slabtext-linesize-0
        {
        line-height:.9;
        }
        /* Just for the demo, adjust the line-height of the second line
           within the preset headline (the line that reads "Jackie Mittoo") */
        #studio-one span:nth-child(2)
        {
        line-height:.9;
        }
        @media screen and (min-width: 460px)
            {
                h1
                    {
                    font-size:26px;
                    }
                h2
                    {
                    font-size:18px;
                    }
            }
        @media screen and (min-width: 760px)
            {
                .col-1
                    {
                    width:47.5%;
                    margin:0 2.5% 0 0;
                    float:left;
                    }
                .col-2
                    {
                    width:47.5%;
                    margin:0 0 0 2.5%;
                    float:left;
                    }
                .col-1 h1,
                .col-2 h1
                    {
                    font-size: 26px;
                    }
                h1
                    {
                    font-size:28px;
                    }
                h2
                    {
                    font-size:20px;
                    }
            }
        @media screen and (min-width: 960px)
            {
                body
                    {
                    width:80%;
                    }
                h1,
                .col-1 h1,
                .col-2 h1
                    {
                    font-size:36px;
                    }
                h2
                    {
                    font-size:22px;
                    }
            }
        @media screen and (min-width: 1180px)
            {
                body
                    {
                    max-width:1200px;
                    }
                h1
                    {
                    font-size:46px;
                    }
                h2
                    {
                    font-size:32px;
                    }
            }
    </style>
    <!--[if lte IE 7]>
    <style>
    body
        {
        width:960px;
        margin:0 auto;
        }
    </style>
    <![endif]-->
    <!--[if lt IE 9]>
    <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
    </head>
    <body>
        <h1 id="h1">slabText &ndash; a jQuery plugin for producing big, bold &amp; responsive headlines</h1>
        <div class="content-wrap">
            <p>I&#8217;ve been wanting to attempt a port of Erik Loyer&#8217;s <a href="http://erikloyer.com/index.php/blog/the_slabtype_algorithm_part_1_background/">slabtype algorithm</a> for quite some time now and seeing Paravel&#8217;s <a href="http://fittextjs.com/">fittext</a> jQuery plugin, in combination with a gloriously hassle-free lunch hour gave me the impetus to attempt it. This is the result &ndash; resize the browser viewport to see the effect in action.</p>
            <h2 id="h2">So what does the script do again?</h2>
            <p>Put simply, the script splits headlines into rows before resizing each row to fill the available horizontal space. The ideal number of characters to set on each row is calculated by dividing the available width by the pixel font-size &ndash; the script then uses this <em>ideal character count</em> to split the headline into word combinations that are displayed as separate rows of text. Many, many <a href="#h12">more examples</a> can be viewed further down the page.</p>
            <h2 id="h3">Calculated and preset word combinations</h2>
            <p>While the script does an admirable job at automating the creation of the individual rows, there are certainly situations in which you would choose to control the word combinations used to split the headline.</p>
            <p>This can be achieved by presetting the word combinations (using <code>&lt;span class="slabtext"&gt;</code> wrappers) within the markup<sup><a href="#fn1" id="r1">[1]</a></sup>. Should the script detect that the headline has been preset, it will not attempt to dynamically create the word combinations and simply fallback to resizing the preset rows to fit the available horizontal space.</p>
            <p>Adding the <code>span</code> elements to the page markup in this way gives you absolute control over the word combinations used to split the headline text and also enables the targetting of specific rows within the CSS (in order to tweak the line height, change the font family etc).</p>
            <p>Presetting the headline does have its drawbacks though &ndash; at smaller sizes and if the rows have wildly varying letter-counts, jagged right edges may be displayed. The script will adjust the <code>word-spacing</code> or <code>letter-spacing</code> in an attempt to rectify over-shoots or under-shoots in line length like this.</p>
            <p>The following demo showcases two versions of the same headline, the first has rows (word combinations) dynamically calculated by the script while the second has rows preset within the markup (and therefore only resized-to-fit by the script).</p>
        </div>
        <div class="col-1">
            <p>The following word combinations have been calculated by the script</p>
            <h1>For one night only Jackie Mittoo with special Studio One guests Dillinger <span class="amp">&amp;</span> Lone&nbsp;Ranger</h1>
        </div>
        <div class="col-2">
            <p>The following word combinations have been preset within the markup</p>
            <h1 id="studio-one"><span class="slabtext">For one night only</span> <span class="slabtext">Jackie Mittoo</span> <span class="slabtext">with special Studio One guests</span> <span class="slabtext">Dillinger <span class="amp">&amp;</span> Lone Ranger</span></h1>
        </div>
        <div class="content-wrap">
        <h2 id="h4" class="u--clear-float">Headers containing links</h2>
        <p>If the original header contains a link (or should itself have an href set), the generated spans will be wrapped in a link that uses the same href.</p>
        <h2 id="h5">Being responsibly responsive</h2>
        <p>You may wish to remove the slabtext treatment entirely should either the viewport or the header element resize to below a certain, predefined width; for example, if the viewport width drops to below 380 pixels. This can be achievied by using the <code>viewportBreakpoint</code> and <code>headerBreakpoint</code> plugin options, <a href="#h6">detailed below</a>.</p>
        <p>This demo page has set <code>viewportBreakpoint</code> to be 380 pixels. Resizing the browser window to anything below this should remove the slabtext treatment from the headlines altogether.</p>
        <h2 id="h6">Behind the scenes</h2>
        <p>In an attempt to keep the plugin as fast as possible, a very basic <code>font-size</code> calculation is ran whenever the <code>window.resize</code> event fires. Headlines that have been preset only fire steps 1, 2, 6 and, if required, 7 &ndash; skipping steps 3 through 5 completely. To save extra cpu cycles, the resize event has been throttled to 300ms.</p>
        <ol>
            <li>The headlines pixel width is calculated.</li>
            <li>The headlines pixel <code>font-size</code> is then calculated.</li>
            <li>The ideal number of &#8220;characters per line&#8221; is derived by dividing the width (calculated in step 1) by the <code>font-size</code> (calculated in step 2) which itself is multiplied by the font scale ratio (which defaults to 0.78) e.g. for a parent container width of 800 pixels and a font-size of 45 pixels the ideal number of characters per line would be calculated using <code>Math.floor(800 / (45 &times; 0.78)) = 22</code>.</li>
            <li>The headline text is then split into words (by splitting on the space character) and these words arranged into combinations containing &lt;= the number of ideal characters per line (calculated in step 3).</li>
            <li>Each word combination is then wrapped in a <code>&lt;span class="slabtext"&gt;</code> element and the headline markup updated with the new content.</li>
            <li>Each individual <code>span</code> then has its <code>font-size</code> adjusted by multiplying the current <code>font-size</code> by the ratio difference between the parent containers width (calculated in step 1) and the width of the <code>span</code>.</li>
            <li>If required, each individual <code>span</code> then has either its <code>letter-spacing</code> (if the line contains only one word) or its <code>word-spacing</code> (if the line contains multiple words) adjusted in an attempt to prod the browser into rectifying over-shoots or under-shoots in line length caused by the previous <code>font-size</code> adjustment.</li>
        </ol>
        <h2 id="h7">Plugin options</h2>
        <p>The following options can currently be passed to the plugin. The first three listed (<code>fontRatio</code>, <code>forceNewCharCount</code> and <code>wrapAmpersand</code>) are only used whenever the plugin has to dynamically create the word combinations i.e. if <code>&lt;span class="slabtext"&gt;</code> elements are <em>not</em> already present within the markup.</p>
        <dl>
            <dt>fontRatio</dt>
            <dd>A floating point value that is used when calculating the ideal number of &#8220;characters per line&#8221;. Defaults to 0.78.</dd>
            <dt>forceNewCharCount</dt>
            <dd>A Boolean value that instructs the script to recalculate the ideal number of &#8220;characters per line&#8221; and reinsert the spans every time the resize event fires (TRUE) or only whenever the parent containers <code>font-size</code> changes (FALSE). Setting this value to FALSE will inevitably save CPU cycles but is only really of use in modern browsers that respond to media queries. Defaults to TRUE.</dd>
            <dt>wrapAmpersand</dt>
            <dd>A Boolean value that instructs the script to wrap ampersands (&amp;) in a <code>&lt;span class="amp"&gt;</code> (TRUE) or not (FALSE). Defaults to TRUE.</dd>
            <dt>maxFontSize</dt>
            <dd>An Integer value that indicates the maximum pixel <code>font-size</code> that the script can set. Defaults to 999.</dd>
            <dt>viewportBreakpoint</dt>
            <dd>An Integer value that indicates the minimum pixel width the viewport may have before the slabtext treatment is removed. There is no default value.</dd>
            <dt>headerBreakpoint</dt>
            <dd>An Integer value that indicates the minimum pixel width the header may have before the slabtext treatment is removed. There is no default value.</dd>
            <dt>noResizeEvent</dt>
            <dd>A Boolean value that instructs the script to ignore the <code>window.resize</code> event (TRUE)  or not (FALSE). Useful for those of you using a fixed width layout. Defaults to FALSE.</dd>
            <dt>resizeThrottleTime</dt>
            <dd>An Integer value that indicates the number of milliseconds the <code>window.resize</code> will be throttled to. Defaults to 300.</dd>
            <dt>precision</dt>
            <dd>An Integer value that indicates the decimal precision to use when setting the CSS values <code>line-height</code>, <code>word-spacing</code> and <code>font-size</code>. Defaults to 3.</dd>
            <dt>postTweak</dt>
            <dd>A Boolean value that instructs the script to tweak the <code>line-height</code> or <code>word-spacing</code> after the <code>font-size</code> calculation has been ran (TRUE) or not (FALSE). Defaults to TRUE.</dd>
            <dt>minCharsPerLine</dt>
            <dd>An optional Integer value that indicates the minimum number of characters to set per line. Headlines that have a character count smaller than this value are not given the slabText treatment.</dd>
            <dt>onRender</dt>
            <dd>An optional function that is called every time the script recalculates the headline.</dd>
        </dl>
        <h2 id="h8">A note on the CSS</h2>
        <p>The plugin requires the following CSS rules are made available:</p>
        <pre><code><span class="hl-2">.slabtexted .slabtext</span>
    {
    <span class="hl-1">display</span>: -moz-inline-box;
    <span class="hl-1">display</span>: inline-block;
    <span class="hl-1">white-space</span>: nowrap;
    }
<span class="hl-2">.slabtextinactive .slabtext</span>
    {
    <span class="hl-1">display</span>: inline;
    <span class="hl-1">white-space</span>: normal;
    <span class="hl-1">font-size</span>: 1em !important;
    <span class="hl-1">letter-spacing</span>: inherit !important;
    <span class="hl-1">word-spacing</span>: inherit !important;
    *<span class="hl-1">letter-spacing</span>: normal !important;
    *<span class="hl-1">word-spacing</span>: normal !important;
    }
<span class="hl-2">.slabtextdone .slabtext</span>
    {
    <span class="hl-1">display</span>: block;
    }</code></pre>
        <p>The <code>span</code> elements added to the headline are given the class <code>slabtext</code> and the document <code>body</code> given the class <code>slabtexted</code>.</p>
        <p>Using a double-whammy className inheritance trick like this means that you can safely add the <code>&lt;span class="slabtext"></code> elements into the markup but they won&#8217;t actually get styled until the script gets called and the <code>slabtexted</code> classname added to the <code>body</code>.</p>
        <p>The <code>span</code> elements are set as <code>display:inline-block</code> during the font-size calculation. This is to take advantage of the <code>inline-block</code> shrink-wrap effect that enables the script to determine the width of each row.</p>
        <p>Unfortunately, one side-effect of using <code>inline-block</code> means that the injected <code>span</code> elements react to surrounding whitespace (which, amongst other things, augments the vertical spacing between rows) &ndash; this is remedied by giving the header a classname of <code>slabtextdone</code> whenever the <code>font-size</code> calculation is complete, which sets a <code>display:block</code> style and avoids the whitespace and styling issues associated with  <code>inline-block</code>.</p>
        <h3 id="h8-1">Legacy Internet Explorer</h3>
        <p>Sharp-eyed readers may have noticed that the value of <code>normal</code> is passed to legacy Internet Explorer versions using the star-hack. This is because IE &lt; 8 doesn&#8217;t understand the <code>inherit</code> property and so we reset to <code>normal</code> as a failsafe.</p>
        <h3 id="h8-2">Save an HTTP request</h3>
        <p>The CSS file is miniscule and you may wish to set-up a task runner to concatenate it into your main CSS file during the build process.</p>
        <h3 id="h8-3">Tweaking line-height</h3>
        <p>Each <code>span</code> element is also given a classname of the form <code>slabtext-linesize-[N]</code> (where <code>N</code> is an Integer value representing the floored result of dividing the character count by ten) and a classname of the form <code>slabtext-linelength-[N]</code> (where <code>N</code> is an Integer value representing the character count). This enables you to target shorter lines that will be rendered at a larger <code>font-size</code> and adjust their <code>line-height</code> accordingly.</p>
        <h3 id="h8-4">Widowed words within headlines</h3>
        <p>It&#8217;s also worth noting that any non-breaking space character used to prevent widowed words within the original, non-adjusted headline will also be included within the adjusted headline.</p>
        <h2 id="h9">Buyer beware</h2>
        <p>Here are a few things to remember when using the plug-in:</p>
        <ol>
            <li>Headlines with lots of horizontal space to fill are more gracefully displayed across browsers.</li>
            <li>Headlines with little horizontal space tend to have jagged right edges, especially if the rows have been preset within the markup and each row has a wildly varying letter-count. Firefox appears to be the best at resizing-to-fit the word combinations and some fonts tend to be better than others at being resized-to-fit.</li>
            <li>The element to be given the slabText treatment has its (inner)HTML replaced entirely (by using the jQuery <code>.html</code> method), which means that all images and links contained within will disappear without a trace.</li>
            <li>Unlike the original <a href="http://erikloyer.com/index.php/blog/the_slabtype_algorithm_part_1_background/">slabtype algorithm</a>, vertical space is not taken into consideration at all.</li>
            <li>If the header contains multiple links, only the first link located is taken into account.</li>
            <li>Internet Explorer 6, due to its non-support of <code>inline-block</code>, cannot scale <em>down</em> the text when the browser viewport is reduced in width. This will not be an issue if you serve a fixed width design to IE6 and fluid width design to other, more capable browsers.</li>
            <li>Internet Explorer &lt; 8 does not support the CSS value of <code>inherit</code> which means that the <code>letter-spacing</code> and <code>word-spacing</code> have to get reset to zero whenever the slabText treatment is removed by the script.</li>
            <li>Always call the script <em>after</em> all <code>fontface</code> fonts have downloaded. I&#8217;ve used the google fontloader <code>fontactive()</code> and <code>fontinactive()</code> callbacks to launch the slabText treatment in the demo.</li>
        </ol>
        <h2 id="h10">Credit where credit&#8217;s due</h2>
        <p>Based on the nice, shiny <a href="http://fittextjs.com/">fittext</a> jQuery plugin by <a href="http://paravelinc.com/">Paravel</a> &amp; the wonderful <a href="http://erikloyer.com/index.php/blog/the_slabtype_algorithm_part_1_background/">slabtype algorithm</a> by Erik Loyer. Zach Leatherman has also written a jQuery plugin named <a href="http://www.zachleat.com/web/bigtext-makes-text-big/">BigText</a> with similar but not exact functionality which is well worth a visit.</p>
        <h2 id="h11">Grab the code</h2>
        <p>The code can be <a href="http://github.com/freqDec/slabText/">downloaded from github</a>. Both minified and unminified versions are included within the bundle. The minified version currently clocks-in at 3k &ndash; this drops to around 2k when gzipped.</p>
        <h2 id="h12">A few more examples</h2>
        <p>As way of example, here&#8217;s a random assortment of book titles (Note: I&#8217;ve left widowed words in all of them).</p>
    </div>
    <h1>The Sisters Brothers</h1>
    <hr />
    <h1>Sometimes a Great Notion</h1>
    <hr />
    <h1>The Peculiar Memories of Thomas Penman</h1>
    <hr />
    <h1>The curious incident of the dog in the night</h1>
    <hr />
    <h1>Something Happened</h1>
    <hr />
    <h1>The sad tale of the brothers Grossbart</h1>
    <hr />
    <h1>The Windup Girl</h1>
    <hr />
    <h1>When Gravity Fails</h1>
    <hr />
    <h1>Psychotic Reactions and Carburetor Dung</h1>
    <hr />
    <h1>Mortal Engines</h1>
    <hr />
    <h1>Tales of Ordinary Madness</h1>
    <hr />
    <h1>Mansfield Park</h1>
    <hr />
    <h1>The Importance of being Earnest</h1>
    <hr />
    <h1>The Scarlet Letter</h1>
    <hr />
    <h1>I Know This Much is True</h1>
    <hr />
    <h1><a href="http://en.wikipedia.org/wiki/Dracula" title="The Dracula wikipedia page">Dracula</a></h1>
    <footer>
        <p id="fn1"><a href="#r1">(1)</a> Of course, you can always use Javascript to inject the <code>&lt;span class="slabtext"&gt;</code> elements into the headline before calling the plugin &ndash; which would keep the markup squeaky clean and cruft free. Here&#8217;s a quick example of how it might be done:</p>
        <pre><code><span class="hl-1">var</span> stS = <span class="hl-2">"&lt;span class='slabtext'>"</span>,
    stE = <span class="hl-2">"&lt;/span>"</span>,
    txt = [
        <span class="hl-2">"For one night only"</span>,
        <span class="hl-2">"Jackie Mittoo"</span>,
        <span class="hl-2">"with special Studio One guests"</span>,
        <span class="hl-2">"Dillinger &amp; Lone Ranger"</span>];

$(<span class="hl-2">"#myHeader"</span>).<span class="hl-1">html</span>(stS + txt.<span class="hl-1">join</span>(stE + stS) + stE).slabText();</code></pre>
    </footer>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
    <script src="js/jquery.slabtext.min.js"></script>
    <script>
    // Function to slabtext the H1 headings
    function slabTextHeadlines() {
        $("h1").slabText({
            // Don't slabtext the headers if the viewport is under 380px
            "viewportBreakpoint":380
        });
    };

    // Load fonts using google font loader
    var WebFontConfig = {
        google: { families: [ 'Open+Sans:400,700:latin', 'Oswald:700:latin' ] },
        // slabText the headers when the font has finished loading (or not)
        fontactive: slabTextHeadlines,
        fontinactive: slabTextHeadlines
    };
    (function() {
        var wf = document.createElement('script');
        wf.src = 'https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
        wf.type = 'text/javascript';
        wf.async = 'true';
        var s = document.getElementsByTagName('script')[0];
        s.parentNode.insertBefore(wf, s);
    })();
    </script>
</body>
</html>
